<template>
  <div class="editor n_b_r">
    <!-- 类名为做一些基本的边框设置 -->
    <Toolbar
      class="toolbar-container"
      :editor="editor"
      :defaultConfig="toolbarConfig"
      mode="default"
      v-if="toolbarVisible"
    />
    <!-- 高度外部页面可调,受制于插件,最小值为300px -->
    <!-- defaultConfig: 配置项 -->
    <!-- 方法 onCreated必须有, onChange可以没有,这里加是为了在外部页面取值-->
    <Editor
      :style="{ height }"
      class="editor-container"
      v-model="html"
      :defaultConfig="editorConfig"
      mode="default"
      @onCreated="onCreated"
      @onChange="onChange"
    />
  </div>
</template>

<script>

import { Boot } from '@wangeditor/editor'
import attachmentModule from '@wangeditor/plugin-upload-attachment'

// 注册。要在创建编辑器之前注册，且只能注册一次，不可重复注册。
Boot.registerModule(attachmentModule)

import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
// 接口
import api from './api.js'

import '@wangeditor/editor/dist/css/style.css'

export default {
  name: 'editor-component',
  props: {
    //路径
    path: {
      type: String,
      default: 'temp'
    },

    // 初始值
    initHtml: String,
    // 是否只读
    readOnly: {
      type: Boolean,
      default: false
    },
    toolbarVisible: {
      type: Boolean,
      default: true
    },
    // ........
    placeholder: {
      type: String,
      default: '请输入内容'
    },
    // 小于300px无效
    editorHeight: {
      type: String,
      default: '300px'
    }
  },
  data() {
    return {
      editor: null,
      toolbarConfig: {
        // 插入哪些菜单
        insertKeys: {
          index: 0, // 自定义插入的位置
          keys: ['uploadAttachment'] // “上传附件”菜单
        },
        // excludeKeys文档里有讲到: 一般用于大部分默认功能都需要, 只有少部分功能不需要, 用这个来排除
        // 查看全部功能使用:  this.editor.getAllMenuKeys()
        excludeKeys: [
          'todo',
          'ondo',
          'insertLink',
          'insertTable',
          'deleteTable',
          'insertTableRow',
          'deleteTableRow',
          'insertTableCol',
          'deleteTableCol',
          'tableHeader',
          'tableFullWidth',
          'blockquote',
          'numberedList'
        ]
      },
      html: '',
      // 语义化的不写注释了好累
      autoFocus: false,
      editorConfig: {
        autoFocus: this.autoFocus,
        placeholder: this.placeholder,
        readOnly: this.readOnly,

        // 在编辑器中，点击选中“附件”节点时，要弹出的菜单
        hoverbarKeys: {
          attachment: {
            menuKeys: ['downloadAttachment'] // “下载附件”菜单
          }
        },
        MENU_CONF: {
          // “上传附件”菜单的配置
          uploadAttachment: {
            timeout: 5 * 1000, // 5s
            maxFileSize: 10 * 1024 * 1024, // 10M
            // // 用户自定义上传
            customUpload(file, insertFn) {
              // this.uploadAttachment(file, insertFn)
              let formData = new FormData()
              formData.append('file', file)

              api.uploadFile('study/attachment', formData).then((res) => {
                insertFn(file.name, res.data) // url, poster(视频封面)
              })

            }
          },
          uploadImage: {
            maxFileSize: 1 * 1024 * 1024,
            // 这个我理解的是上传文件个数..但我试了, 妹有用
            maxNumberOfFiles: 4,
            allowedFileTypes: [
              'image/jpeg',
              'image/jpg',
              'image/png',
              'image/svg',
              'image/gif',
              'image/webp'
            ],
            timeout: 6 * 1000,
            // 自定义上传图片的方法
            customUpload: (file, insertFn) => {
              this.uploadImage(file, insertFn)
            }
          },
          uploadVideo: {
            maxNumberOfFiles: 1,
            maxFileSize: 100 * 1024 * 1024,
            allowedFileTypes: [
              'video/mp4',
              'video/3gp',
              'video/m3u8'
            ],
            timeout: 6 * 1000,
            customUpload: (file, insertFn) => {
              this.uploadVideo(file, insertFn)
            }
          },
          codeSelectLang: {
            // 代码语言
            codeLangs: [
              { text: 'CSS', value: 'css' },
              { text: 'HTML', value: 'html' },
              { text: 'XML', value: 'xml' }
              // 其他
            ]
          }
        }
      }
    }
  },
  computed:
    {
      // 限制editor高度
      height() {
        return parseInt(this.editorHeight) < 300
          ? '300px'
          : this.editorHeight
      }
    }
  ,
  methods: {
    customPaste: (editor, event) => {
      console.log('触发customPaste')
      if (!editor.insertImage) {
        return
      }
      if (!this.uploadImage) {
        return
      }
      // event 是 ClipboardEvent 类型，可以拿到粘贴的数据
      // 可参考 https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardEvent

      // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
      // const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
      // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据（如从 word wsp 复制粘贴）
      if (event.clipboardData && event.clipboardData.items[0].type === 'image/png') {
        const file = event.clipboardData.files[0] // 获取复制的图片文件对象
        this.uploadImage(file, editor.insertImage)
      }
    },
    onCreated(editor) {
      this.editor = Object.seal(editor)
    }
    ,
    onChange() {
      // 输入框内值发生变化时需要向外传值
      this.$emit('change', this.html)
    }
    ,
    uploadImage(file, insertFn) {
      let formData = new FormData()
      formData.append('file', file)

      api.uploadFile(this.path, formData).then((res) => {
        // 接口返回的路径----将图片插入页面
        // insertFn是上面自定义上传的方法中传递的参数方法, 本身有仨参数
        // url, alt, href
        insertFn(res.data, file.name, res.url)
      })
    },

    uploadVideo(file, insertFn) {
      let formData = new FormData()
      formData.append('file', file)

      api.uploadFile(this.path, formData).then((res) => {
        insertFn(res.data, '') // url, poster(视频封面)
      })
    },

    //上传附件
    uploadAttachment(file, insertFn) {

    }

  }
  ,
  components: {
    Editor, Toolbar
  }
  ,
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) {
      return
    }
    editor.destroy()
  }
  ,
  watch: {
    // 将外部页面赋的值传递到组件area中
    initHtml: {
      handler(value) {
        this.html = value
        this.autoFocus = this.html === ''
      }
      ,
      immediate: true
    }
  }
}
</script>

<style scoped>


.editor {
  border: 1px solid #eee;
  z-index: 999;
}

.editor-container {
  min-height: 300px;
}

.toolbar-container {
  border-bottom: 1px solid #ccc;
  border-top: 1px solid transparent;
}
</style>
